/* Class: UWA.Environment

The Environment Base class provide base functions to run a Module Execution Environnement.
It is an abstract class, and must be extended to be useful.
The object must be filled with DOM elements (at least body), in the "<onInit>" or "<onRegisterModule>" callbacks for example.

_Copyright 2006-2007 Netvibes. All rights reserved._
*/

if (typeof UWA == "undefined") var UWA = {};

UWA.Environment = function() {

    /* Property: module

    *Module*: current module registered in this environnement.
    */
    this.module = false;
    
    this.widget = this.module;
    
    /* Property: html

    *String*: HTML Dom elements of this environnement
    */
    this.html = {};
     
    /* Property: loaded

    *Boolean*: flag to know if the Environnement is ready.
    */
    this.loaded = false;
  
    /* Property: registered

    *Boolean*: flag to know if the Module is registered.
    */
    this.registered = false;
    
    /* Property: callbacks 

    *Collection{Function}*: _experimental_ collection of callback methods.
    */
    this.callbacks = {};

    /* Property: query

    *String*: _experimental_ query string.
    */
    this.query = ''; // where is it used ?

    /* Property: data

    *Collection{Object}*: _experimental_ data.
    */
    this.data = {};

    /* Property: debugMode

    *Boolean*: activates (or not) the debug mode (display message in console).
    */    
    this.debugMode = false;
    
    /* Property: periodicals

    *Collection{Object}*: store periodicals events
    */
    this.periodicals = {};
    
    /* Property: delays

    *Collection{Object}*: store delayed events
    */
    this.delays = {};
    
    /* to document */
    this.height = 200;
    
    if(this.initialize) this.initialize();
    
    this.setPeriodical('init', this.init, 100, true);

}

UWA.Environment.prototype = {
  
  /* Method: init

  Initialize the Environment, when DOM is ready

  Parameters:
  * None.

  Returns:
  * Nothing.
  */ 
  init: function() {
    if (document.body) {
      this.callback('onInit');
      this.clearPeriodical('init');
      this.log('Environnement loaded');
      this.loaded = true;
      return true;
    }
    return false;
  },

  /* Method: getModule

  Returns the module currently registered in the Environment. 
  If no module is registered, the Environment creates one and registers it.

  Parameters:
  * None.

  Returns:
  * Module: the (maybe newly created) registered module.
  */ 
  getModule: function() {
    if (this.module) {
      var module = this.module;
    } else {
      var module = new UWA.Module();
      this.registerModule(module);
    }
    return module;
  },
  
  /* Method: registerModule

  Registers a Module into the execution Environment (tries to "<launch _register>" until the Environment is ready).

  Parameters:
  * Module : the module to register in the Environment.

  Returns:
  * Nothing.
  */ 
  registerModule: function(module) {
    this.module = module;
    this.widget = this.module;
    module.environment = this;
    this.setPeriodical('register', function() {
      if (this.loaded) {
        this.callback('onRegisterModule');
        this.registered = true;
        this.log('Module registered');
        this.clearPeriodical('register');
      }
    }, 100, true);
  },

  /* Method: launchModule

  Launches the registered module, or the module given as a parameter

  Parameters:
  * Module - module: (optional) to launch another module than the registered module.

  Returns:
  * Nothing.
  */
  launchModule: function() {
    this.setPeriodical('launch', function() {
      if (this.loaded && this.module && this.registered) {
          this.log('Launching module');
          this.module.launch();
          this.clearPeriodical('launch');
          if (this.query && this.query != '' && this.module.onSearch) {
              this.module.onSearch(this.query); // to move in a callback ? seems used in frame env ...
          } 
      }
    }, 100, true);
  },
  
  /* Method: setCallback

  Stores an association of callback function with the name of the event that fires them.

  Parameters:
  * String - name: name of the event,
  * Function - fn: the callback function to fire for the event.

  Returns:
  * Nothing.
  */
  setCallback: function(name, fn) {
    this.callbacks[name] = fn;
  },
  
  /* to document */
  callback: function(name, args, bind) {
    if (typeof bind == 'undefined') bind = this;
    try {
      if (this[name]) return this[name].apply(bind, [args]);
      if (this.callbacks[name]) return this.callbacks[name].apply(bind, [args]);
    } catch(e) {
      this.log(e);
    }
    return false;
  },
 
  /* to document */
  setPeriodical: function(name, fn, delay, force) {
    this.clearPeriodical(name);
    fn = fn.bind(this);
    this.periodicals[name] = setInterval(fn, delay);
    if (force) fn();
  },
  
  /* to document */
  clearPeriodical: function(name) {
    if (this.periodicals[name]) { clearInterval(this.periodicals[name]) }
  },
  
  /* to document */
  setDelayed: function(name, fn, delay, bind) {
    this.clearDelayed(name);
    if(typeof bind == "undefined" || bind === true) fn = fn.bind(this);
    this.delays[name] = setTimeout(fn, delay);
  },
  
  /* to document */
  clearDelayed: function(name) {
    if (this.delays[name]) { clearTimeout(this.delays[name]) }
  },
  
  /* to document */
  setIcon: function(url) {
    if(this.module.elements['icon']) this.module.elements['icon'].setHTML('<img width="16" height="16" src="' + url + '" />');
  },
   
  /* Method: log

  If <debugMode> is TRUE, writes log messages in the console. Compatible with Firebug, Safari, Opera...

  Parameters:
  * Strig - string: the string to display.

  Returns:
  * Nothing.
  */
  log: function(string) {
    if (this.debugMode) UWA.log(string);
  }

}
